import tushare as ts
pro = ts.pro_api()
from spec_class import Spec
import pandas as pd

# df = pro.fut_daily(trade_date='20181113', exchange='DCE', fields='ts_code,trade_date,pre_close,pre_settle,open,high,low,close,settle,vol')
# df = pro.fut_daily(ts_code='CU1811.SHF', start_date='20180101', end_date='20181113')
# df = pro.fut_daily(trade_date='20181113', exchange='DCE', fields='ts_code,trade_date,
# pre_close,pre_settle,open,high,low,close,settle,vol')


def get_single_data(name, contract, start, end):
    '''用来抓取单个合约在给定时间周期内的数据'''
    spec = Spec(name)
    req_code = spec.get_code(contract) + '.' + spec.check_exchange()
    ts_data = pro.fut_daily(ts_code=req_code, start_date=start, end_date=end)
    ts_data.drop(ts_data.columns[[2, 3, 8, 9, 10, 12]], axis=1, inplace=True)
    return ts_data


def get_bulk_hld_data(sym, exc):
    '''用来抓取某个给定代码的所有持仓数据'''
    # 因为spec_class内返回的symbol和exchange有可能有区别，所以在这里统一检查并完成替换
    if exc == 'ZCE':
        exc = 'CZCE'
    if exc == 'SHF':
        exc = 'SHFE'
    if sym == 'TA':
        sym = 'PTA'
    df = pro.fut_holding(symbol=sym, exchange=exc)
    df.set_index('trade_date', inplace=True)
    return df


def get_hld_single(bulk_df, date):
    '''用来从拿到的总df中抓取某天某个合约的持仓数据并整理出当天的一列蛛网数据'''
    try:
        bulky = bulk_df.loc[date].copy()
    except:
        result_list = []
    else:
        if isinstance(bulky, pd.Series):
            ifd = (bulky['long_hld'] + bulky['short_hld']) / bulky['vol']
            ts = (bulky['long_chg'] - bulky['short_chg']) / (abs(bulky['long_chg']) + abs(bulky['short_chg']))
            seri2 = pd.Series([ifd, ts], index=['infodex', 'ts'])
            set_seri = bulky.append(seri2)
            set_df = set_seri.to_frame().T
        elif isinstance(bulky, pd.DataFrame):
            df = bulky
            df.eval('infodex = (long_hld + short_hld) / vol', inplace=True)
            df.eval('ts = (long_chg - short_chg) / (abs(long_chg) + abs(short_chg))', inplace=True)
            df.sort_values(by='infodex', ascending=False, inplace=True)
            set_df = df.query("vol > 16")
        length = len(set_df.index.to_list())
        ll = int(length * 0.35)  # 设定知情席位为按照知情指数排名前30%的席位，其余为非知情席位
        rr = length - ll
        bull = set_df.head(ll)['long_chg'].sum()
        bear = set_df.head(ll)['short_chg'].sum()
        # xx = bull * bear
        if (abs(bull) + abs(bear)) == 0:
            signal = 0
        else:
            signal = (bull - bear) / (abs(bull) + abs(bear))
        infavg = set_df.head(ll)['ts'].mean()  # 知情席位的交易情绪平均值
        uninfavg = set_df.tail(rr)['ts'].mean()  # 非知情席位的交易情绪平均值
        result_list = [date, infavg, uninfavg, signal]
    return result_list


def get_holding(bulk_df, sym, exc, date):
    '''用来从总的df中抓取当天的持仓数据, 返回当天的多空情绪列表'''
    if exc == 'SHFE':
        r = 0.5
    else:
        r = 0.35

    try:
        bulky = bulk_df.loc[date].copy()
    except:
        signal_list = []
    else:
        if isinstance(bulky, pd.Series):
            ifd = (bulky['long_hld'] + bulky['short_hld']) / bulky['vol']
            ts = (bulky['long_chg'] - bulky['short_chg']) / (abs(bulky['long_chg']) + abs(bulky['short_chg']))
            seri2 = pd.Series([ifd, ts], index=['infodex', 'ts'])
            set_seri = bulky.append(seri2)
            set_df = set_seri.to_frame().T
        elif isinstance(bulky, pd.DataFrame):
            df = bulky
            df.eval('infodex = (long_hld + short_hld) / vol', inplace=True)
            df.eval('ts = (long_chg - short_chg) / (abs(long_chg) + abs(short_chg))', inplace=True)
            df.sort_values(by='infodex', ascending=False, inplace=True)
            set_df = df.query("vol > 16")
        length = len(set_df.index.to_list())
        ll = int(length * r)  # 设定知情席位为按照知情指数排名前30%的席位，其余为非知情席位
        rr = length - ll
        bull = set_df.head(ll)['long_chg'].sum()
        bear = set_df.head(ll)['short_chg'].sum()
        # xx = bull * bear
        if (abs(bull) + abs(bear)) == 0:
            signal = 0
        else:
            signal = (bull - bear) / (abs(bull) + abs(bear))
        infavg = set_df.head(ll)['ts'].mean()  # 知情席位的交易情绪平均值
        uninfavg = set_df.tail(rr)['ts'].mean()  # 非知情席位的交易情绪平均值
        signal_list = [date, sym, infavg, uninfavg, signal]
    return signal_list

